home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / CAD / LISP04.ARJ / DLINE.LSP < prev    next >
Text File  |  1991-01-28  |  67KB  |  2,099 lines

  1. ;;;   DLine.lsp
  2. ;;;   Copyright (C) 1990-91 by Autodesk, Inc.
  3. ;;;  
  4. ;;;   Permission to use, copy, modify, and distribute this software and its
  5. ;;;   documentation for any purpose and without fee is hereby granted.  
  6. ;;;
  7. ;;;   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 
  8. ;;;   ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF 
  9. ;;;   MERCHANTABILITY ARE HEREBY DISCLAIMED.
  10. ;;; 
  11. ;;;   by Jan S. Yoder
  12. ;;;   5 April 1990
  13. ;;;
  14. ;;;----------------------------------------------------------------------------
  15. ;;;   DESCRIPTION
  16. ;;;     
  17. ;;;     This is a general purpose "double-line/arc" generator.  It performs 
  18. ;;;     automatic corner intersection cleanups, as well as a number of other 
  19. ;;;     features described below.
  20. ;;;  
  21. ;;;     The user is prompted for a series of endpoints.  As they are picked 
  22. ;;;     "DLINE"  segments are drawn on the current layer.  Options are 
  23. ;;;     available for changing the Width of the DLINE, specifying whether
  24. ;;;     or not to Snap to existing lines or arcs, whether or not to 
  25. ;;;     Break the lines or arcs when snapping to them, and which of the 
  26. ;;;     following to do:  
  27. ;;;     
  28. ;;;     Set the global variable dl:ecp to the values listed below:
  29. ;;;  
  30. ;;;     Value  Meaning
  31. ;;;     ---------------------------
  32. ;;;       0    No end caps
  33. ;;;       1    Start end cap only
  34. ;;;       2    Ending end cap only
  35. ;;;       3    Both end caps
  36. ;;;       4    Auto ON -- Cap any end not on a line or arc.
  37. ;;;       
  38. ;;;     The user may choose to back up as far as the beginning of the command 
  39. ;;;     by typing "U" or "Undo", both of which operate as AutoCAD's "UNDO 1" 
  40. ;;;     does.
  41. ;;;     
  42. ;;;     Curved DLINE's are drawn using the AutoCAD ARC command and follow as 
  43. ;;;     closely as possible its command structure for the various options.
  44. ;;;  
  45. ;;;----------------------------------------------------------------------------
  46. ;;;   OPERATION
  47. ;;;
  48. ;;;     The routine is executed, after loading, by typing either DL or DLINE
  49. ;;;     at which time you are presented with the opening line and menu of
  50. ;;;     choices:
  51. ;;;     
  52. ;;;       Dline, Version 1.00, (c) 1990 by Autodesk, Inc.  
  53. ;;;       Break/Caps/Dragline/Offset/Snap/Undo/Width/<start point>: 
  54. ;;;     
  55. ;;;     Typing Break allows you to set breaking of lines and arcs found at
  56. ;;;     the start and end points of any segment either ON or OFF.
  57. ;;;     
  58. ;;;       Break Dline's at start and end points?  OFF/<ON>:
  59. ;;;     
  60. ;;;     Typing Caps allows you to specify how the DLINE will be finished 
  61. ;;;     off when exiting the routine, per the values listed above.
  62. ;;;     
  63. ;;;       Draw which endcaps?  Both/End/None/Start/<Auto>:
  64. ;;;       
  65. ;;;     The default of Auto caps an end only if you did not snap to an arc
  66. ;;;     or line.
  67. ;;;     
  68. ;;;     Typing Dragline allows you to set the location of the dragline
  69. ;;;     relative to the centerline of the two arcs or lines to any value
  70. ;;;     between - 1/2 of "tracewid" and + 1/2 of "tracewid".  (There is a
  71. ;;;     local variable you may set if you want to experiment with offsets
  72. ;;;     outside this range;  the results may not be correct, your choice.
  73. ;;;     See the function (dl_sao) for more information.)
  74. ;;;     
  75. ;;;       Set dragline position to Left/Center/Right/<Offset from center = 0.0>:
  76. ;;;     
  77. ;;;     Enter any real number or one of the keywords.  The value in the angle
  78. ;;;     brackets is the default value and changes as you change the dragline
  79. ;;;     position.
  80. ;;;     
  81. ;;;     Offset allows the first point you enter to be offset from a known
  82. ;;;     point.
  83. ;;;     
  84. ;;;       Offset from:  (enter a point)
  85. ;;;       Offset toward:    (enter a point)
  86. ;;;       Enter the offset distance:   (enter a distance or real number)
  87. ;;;  
  88. ;;;     Snap allows you to set the snapping size and turn snapping ON or OFF.
  89. ;;;     
  90. ;;;       Set snap size or snap On/Off.  Size/OFF/<ON>:
  91. ;;;       New snap size (1 - 10):
  92. ;;;     
  93. ;;;     The upper limit may be reset by changing the value of MAXSNP to a 
  94. ;;;     value other than 10.  Higher values may be necessary for ADI display
  95. ;;;     drivers, but generally, you should keep this value somewhere in the 
  96. ;;;     middle of the allowed range for snapping to work most effectively 
  97. ;;;     in an uncluttered drawing, and toward the lower end for a more 
  98. ;;;     cluttered drawing.  You may also use object snap to improve your 
  99. ;;;     aim.
  100. ;;;     
  101. ;;;     This feature allows you to very quickly "snap" to another line or arc, 
  102. ;;;     breaking it at the juncture and performing all of the intersection 
  103. ;;;     cleanups at one time without having to be precisely on the line, i.e., 
  104. ;;;     you can be visually one the line and it will work, or you can use 
  105. ;;;     object snap to be more precise.
  106. ;;;     
  107. ;;;     Undo backs you up one segment in the chain of segments you are drawing,
  108. ;;;     stopping when there are no more segments to be undone.  All of the 
  109. ;;;     necessary points are saved in lists so that the DLINE will close, cap,
  110. ;;;     and continue correctly after any number of undo's.
  111. ;;;     
  112. ;;;     Width prompts you for a new width.
  113. ;;;     
  114. ;;;       New DLINE width <1.0000>:
  115. ;;;       
  116. ;;;     You may enter a new width and continue the DLINE in the same direction
  117. ;;;     you were drawing before;  if you do this, connecting lines from the
  118. ;;;     endpoints of the previous segment are drawn to the start points of 
  119. ;;;     the new segment.
  120. ;;;     
  121. ;;;     If you press RETURN after closing a DLINE or before creating any
  122. ;;;     DLINE's, you will see this message:
  123. ;;;     
  124. ;;;       No continuation point -- please pick a point.  
  125. ;;;       Break/Caps/Dragline/Offset/Snap/Undo/Width/<start point>:  
  126. ;;;     
  127. ;;;     After you pick the first point, you will see this set of options:
  128. ;;;     
  129. ;;;       Arc/Break/CAps/CLose/Dragline/Snap/Undo/Width/<next point>:
  130. ;;;       
  131. ;;;     Picking more points will draw straight DLINE segments until either 
  132. ;;;     RETURN is pressed or the CLose option is chosen.
  133. ;;;     
  134. ;;;     CLose will close the lines if you have drawn at least two segments.
  135. ;;;     
  136. ;;;     Selecting Arc presents you with another set of choices:
  137. ;;;     
  138. ;;;       Break/CAps/CEnter/CLose/Dragline/Endpoint/Line/Snap/Undo/Width/<second point>:
  139. ;;;     
  140. ;;;     All of the options here are the same as they are for drawing straight
  141. ;;;     DLINE's except CEnter, Endpoint, and Line.
  142. ;;;     
  143. ;;;     The default option, CEnter, and Endpoint are modeled after the ARC
  144. ;;;     command in AutoCAD and exactly mimic its operation including all of
  145. ;;;     the subprompts.  Refer to the AutoCAD reference manual for exact usage.
  146. ;;;     
  147. ;;;     The Line option returns you to drawing straight DLINE segments.
  148. ;;;     
  149. ;;;     Snapping to existing LINE's an ARC's accomplishes all of the trimming 
  150. ;;;     and extending of lines and arcs necessary, including cases where arcs 
  151. ;;;     and lines do not intersect.  In these cases a line is drawn from either;
  152. ;;;     a point on the arc at the perpendicular point from the center of the 
  153. ;;;     arc to the line, to the line, or along the line from the centers of the
  154. ;;;     two arcs that do not intersect at the points where this line crosses
  155. ;;;     the two arcs.  In this way, we ensure that all DLINE's can be closed
  156. ;;;     visually.
  157. ;;;     
  158. ;;;     Breaking will not work unless Snapping is turned on.
  159. ;;;     
  160. ;;;     
  161. ;;;     
  162. ;;;   REVISIONS    
  163. ;;;     Version 1.00a -- Bug fix for arcs crossing over themselves.
  164. ;;;                      
  165. ;;;                      Various other fixes.
  166. ;;;       
  167. ;;;     Version 1.00b -- Bug fix for arcs starting at end of arcs,
  168. ;;;                      lines starting on lines and parallel.
  169. ;;;       
  170. ;;;     Version 1.00c -- Another bug fix for arcs starting at end of arcs.
  171. ;;;       
  172. ;;;       
  173. ;;;       
  174. ;;;       
  175. ;;;----------------------------------------------------------------------------
  176. ;;;  GLOBALS:
  177. ;;;     dl:osd -- dragline alignment offset from center of two lines or arcs.
  178. ;;;     dl:snp -- T if snapping to existing lines and arcs.
  179. ;;;     dl:brk -- T if breaking existing lines and arcs.
  180. ;;;     dl:ecp -- Bitwise setting of caps when exiting.
  181. ;;;     v:stpt -- Continuation point.
  182. ;;;----------------------------------------------------------------------------
  183. ;;; Main function
  184.  
  185. (defun dline  (/ strtpt nextpt pt1    pt2    spts   wnames elast
  186.                  uctr   pr     prnum  temp   ans    dir    ipt
  187.                  v      lst    dist   cpt    rad    orad   ftmp
  188.                  spt    ept    pt     en1    en2    npt    cpt1
  189.                  flg    cont   flg2   flgn   ang    tmp    
  190.                  brk_e1 brk_e2 bent1  bent2  nn     nnn    
  191.                  dl_osm dl_oem dl_oce dl_opb dl_obm dl_ver 
  192.                  dl_err dl_oer dl_arc fang   MAXSNP ange   
  193.                  savpt1 savpt2 savpt3 savpt4 savpts 
  194.               )
  195.  
  196.   ;; Version number.  Reset this local if you make a change.
  197.   (setq dl_ver "1.00c")  
  198.   
  199.   ;; Reset this value higher for ADI drivers.
  200.   (setq MAXSNP 10)              
  201.  
  202.   (setq dl_osm (getvar "osmode")
  203.         dl_oem (getvar "expert")
  204.         dl_oce (getvar "cmdecho")
  205.         dl_opb (getvar "pickbox")
  206.         dl_obm (getvar "blipmode")
  207.   )
  208.  
  209.   ;;
  210.   ;; Internal error handler defined locally
  211.   ;;
  212.  
  213.   (defun dl_err (s)                   ; If an error (such as CTRL-C) occurs
  214.                                       ; while this command is active...
  215.     (if (/= s "Function cancelled")
  216.       (if (= s "quit / exit abort")
  217.         (princ)
  218.         (princ (strcat "\nError: " s))
  219.       )
  220.     )
  221.     (command "undo" "en")
  222.     (if dl_oer                        ; If an old error routine exists
  223.       (setq *error* dl_oer)           ; then, reset it 
  224.     )
  225.     (if dl_osm (setvar "osmode" dl_osm))
  226.     (if dl_oem (setvar "expert" dl_oem))
  227.     (if dl_opb (setvar "pickbox" dl_opb))
  228.     (if dl_obm (setvar "blipmode" dl_obm))
  229.     
  230.     ;; Reset command echoing on error
  231.     (if dl_oce (setvar "cmdecho" dl_oce))      
  232.     (princ)
  233.   )
  234.   
  235.   ;; Set our new error handler
  236.   (if (not *DEBUG*)
  237.     (if *error*
  238.       (setq dl_oer *error* *error* dl_err)
  239.       (setq *error* dl_err)
  240.     )
  241.   )
  242.  
  243.   (setvar "cmdecho" 0)
  244.   (setvar "osmode" 0)
  245.   (setvar "expert" 4)
  246.   (setvar "blipmode" 0)
  247.   (if (null dl:opb) (setq dl:opb (getvar "pickbox")))
  248.  
  249.   (command "undo" "group")
  250.   
  251.   (setq nextpt "Straight")
  252.  
  253.   ;; Get the first segment's start point
  254.  
  255.   (menucmd "s=dline1")
  256.   (graphscr)
  257.   (princ (strcat "\nDline, Version " dl_ver ", (c) 1990 by Autodesk, Inc. "))
  258.   
  259.   (setq cont T)
  260.   (while cont
  261.     (dl_m1)
  262.  
  263.     ;; Ready to draw successive DLINE segments
  264.  
  265.     (dl_m2)
  266.   )
  267.   
  268.   (if dl_osm (setvar "osmode" dl_osm))
  269.   (if dl_oem (setvar "expert" dl_oem))
  270.   (if dl_opb (setvar "pickbox" dl_opb))
  271.   (if dl_obm (setvar "blipmode" dl_obm))
  272.   ;; Reset command echoing
  273.   (if dl_oce (setvar "cmdecho" dl_oce))      
  274.   (menucmd "s=s")
  275.   (princ)
  276. )
  277. ;;;
  278. ;;; Main function subsection 1.
  279. ;;;
  280. ;;; dl_m1 == DLine_Main_1
  281. ;;;
  282. (defun dl_m1 ()
  283.   (setq temp T
  284.         uctr nil 
  285.   )
  286.   (if dl_arc
  287.     (setq nextpt "Arc")
  288.     (setq nextpt "Line")
  289.   )
  290.   ;; temp set to nil when a valid point is entered.
  291.   (while temp
  292.     (initget "Break Caps Dragline Offset Snap Undo Width")
  293.     (setq strtpt (getpoint 
  294.       "\nBreak/Caps/Dragline/Offset/Snap/Undo/Width/<start point>: "))
  295.     (cond
  296.       ((= strtpt "Dragline")
  297.         (dl_sao)
  298.       )
  299.       ((= strtpt "Break")
  300.         (initget "ON OFf")
  301.         (setq dl:brk (getkword 
  302.           "\nBreak Dline's at start and end points?  OFf/<ON>: "))
  303.         (setq dl:brk (if (= dl:brk "OFf") nil T))    
  304.       )
  305.       ((= strtpt "Offset")
  306.         (dl_ofs)
  307.       )
  308.       ((= strtpt "Snap")
  309.         (dl_sso)
  310.       )
  311.       ((= strtpt "Undo")
  312.         (princ "\nAll segments already undone. ")
  313.         (setq temp T)
  314.       )
  315.       ((= strtpt "Width")
  316.         (initget 6)
  317.         (dl_snw)
  318.         (setq temp T)
  319.       )
  320.       ((null strtpt)
  321.         (if v:stpt
  322.           (setq strtpt v:stpt
  323.                 temp   nil
  324.           )
  325.           (progn
  326.             (princ "\nNo continuation point -- please pick a point. ")
  327.           )
  328.         )
  329.       )
  330.       ((= strtpt "Caps")
  331.         (endcap)    
  332.       )
  333.       ;; If none of the above, it must be OK to continue - a point has been 
  334.       ;; picked or entered from the keyboard.
  335.       (T
  336.         (setq v:stpt strtpt
  337.               temp   nil
  338.         )
  339.       )
  340.     )
  341.   )
  342. )
  343. ;;;
  344. ;;; Main function subsection 2.
  345. ;;;
  346. ;;; dl_m3 == DLine_Main_2
  347. ;;;
  348. (defun dl_m2 (/ temp)
  349.   (setq spts (list strtpt)
  350.         uctr 0 
  351.   )
  352.   (if dl:snp
  353.     (dl_ved "brk_e1" strtpt)
  354.   )
  355.   ;; Make sure that the offset is not greater than 1/2 of "tracewid", even
  356.   ;; if the user transparently resets it while the command is running.
  357.   (setq temp (/ (getvar "tracewid") 2.0))
  358.   (if (< dl:osd (- temp))
  359.     (setq dl:osd (- temp))
  360.   )
  361.   (if (> dl:osd temp)
  362.     (setq dl:osd temp)
  363.   )
  364.     
  365.   (while (and nextpt (/= nextpt "CLose"))
  366.     (if (/= nextpt "Quit")
  367.       (if dl_arc 
  368.         (progn
  369.           (menucmd "s=dline2")
  370.           (initget 
  371.             "Break CAps CEnter CLose Dragline Endpoint Line Snap Undo Width")
  372.           (setq nextpt (getpoint strtpt (strcat
  373.             "\nBreak/CAps/CEnter/CLose/Dragline/Endpoint/"
  374.             "Line/Snap/Undo/Width/<second point>: "))
  375.           )
  376.         )
  377.         (progn
  378.           (menucmd "s=dline3")
  379.           (initget "Arc Break CAps CLose Dragline Snap Undo Width")
  380.           (setq nextpt (getpoint strtpt
  381.             "\nArc/Break/CAps/CLose/Dragline/Snap/Undo/Width/<next point>: ")
  382.           )
  383.         )
  384.       )
  385.     )
  386.     (setq v:stpt (last spts))
  387.     (cond
  388.       ((= nextpt "Dragline")
  389.         (dl_sao)
  390.       )
  391.       ((= nextpt "Width")
  392.         (dl_snw)
  393.         
  394.       )
  395.       ((= nextpt "Undo")
  396.         (cond
  397.           ;;((= uctr 0) (princ "\nNothing to undo. ") )
  398.           ((= uctr 0) (setq nextpt nil) )
  399.           ((> uctr 0) 
  400.             (command "u")
  401.             (setq spts   (dl_lsu spts 1))
  402.             (setq savpts (dl_lsu savpts 2))
  403.             (setq wnames (dl_lsu wnames 2))
  404.             (setq uctr (- uctr 2))
  405.             (setq strtpt (last spts))
  406.           )
  407.         ) 
  408.         (if dl:snp
  409.           (if (= uctr 0)
  410.             (dl_ved "brk_e1" strtpt)
  411.           ) 
  412.         ) 
  413.       )
  414.       ((= nextpt "Break")
  415.         (initget "ON OFf")
  416.         (setq dl:brk (getkword 
  417.           "\nBreak Dline's at start and end points?  OFF/<ON>: "))
  418.         (setq dl:brk (if (= dl:brk "OFf") nil T))    
  419.         
  420.         (if dl:snp
  421.           (dl_ved "brk_e1" strtpt)
  422.         )
  423.         (if dl_arc
  424.           (setq nextpt "Arc")
  425.           (setq nextpt "Line")
  426.         )
  427.       )
  428.       ((= nextpt "Snap")
  429.         (dl_sso)
  430.       )
  431.       ((= nextpt "Arc")
  432.         (setq dl_arc T)               ; Change to Arc segment prompt.
  433.       )
  434.       ((= nextpt "Line")
  435.         (setq dl_arc nil)             ; Change to Line segment prompt.
  436.       )
  437.       ((= nextpt "CLose")
  438.         (dl_cls)
  439.       )
  440.       ((= (type nextpt) 'LIST)
  441.         (dl_ds)
  442.       )
  443.       ((= nextpt "CEnter")
  444.         (dl_ceo)
  445.       )
  446.       ((= nextpt "Endpoint")
  447.         (dl_epo)
  448.       )
  449.       ((= nextpt "CAps")
  450.         (endcap)                      ; Set which caps to draw when exiting.
  451.       )
  452.       (T
  453.         (setq nextpt nil cont nil)
  454.         (if (> uctr 1)
  455.           (if (= (logand 4 dl:ecp) 4)
  456.             (progn
  457.               (if (null brk_e1) (command "line" savpt1 savpt2 ""))
  458.               (dl_ssp)
  459.               (if (null brk_e2) (command "line" savpt3 savpt4 ""))
  460.             )
  461.             (progn
  462.               (if (= (logand 1 dl:ecp) 1)
  463.                 (command "line" savpt1 savpt2 "")
  464.               )
  465.               (if (= (logand 2 dl:ecp) 2)
  466.                 (progn
  467.                   (dl_ssp)
  468.                   (command "line" savpt3 savpt4 "")
  469.                 )
  470.               )
  471.             )
  472.           )
  473.         )
  474.         (if brk_e1 (setq brk_e1 nil))
  475.         (if brk_e2 (setq brk_e2 nil))
  476.         (command "undo" "en")
  477.       )                               ; end of inner cond  
  478.     )                                 ; end of outer cond  
  479.   )                                   ; end of while
  480. )
  481. ;;; ------------------ End Main Functions ---------------------------
  482. ;;; ---------------- Begin Support Functions ------------------------
  483.  
  484.  
  485. ;;;
  486. ;;; Close the DLINE with either straight or arc segments.  
  487. ;;; If closing with arcs, the minimum number of segments already drawn
  488. ;;; is 1, otherwise it is 2.
  489. ;;;
  490. ;;; dl_cls == DLine_CLose_Segments
  491. ;;;
  492. (defun dl_cls ()
  493.   (if (or (and (null dl_arc) (< uctr 4)
  494.                (if (> uctr 1)
  495.                  (/= (dl_val 0 (entlast)) "ARC")
  496.                  (not (> uctr 1))
  497.                )
  498.           )
  499.           (and dl_arc (< uctr 2)))
  500.     (progn 
  501.       (princ "\nCannot close -- too few segments. ")
  502.       (if dl_arc
  503.         (setq nextpt "Arc")
  504.         (setq nextpt "Line")
  505.       )
  506.     )
  507.     (progn
  508.       (command "undo" "group")
  509.       (setq nextpt (nth 0 spts))
  510.       (if (null dl_arc)
  511.         ;; Close with line segments
  512.         (dl_mlf 3)
  513.         (progn
  514.           (setq tmp (last wnames)
  515.                 ange (trans '(1 0 0) (dl_val -1 tmp) 1)
  516.                 ange (angle '(0 0 0) ange)
  517.                 dir (if (= (dl_val 0 tmp) "LINE")
  518.                       (angle (trans (dl_val 10 tmp) 0 1) 
  519.                              (trans (dl_val 11 tmp) 0 1))
  520.                       (progn
  521.                         (setq dir (+ (dl_val 50 tmp) ange)
  522.                               dir (if (> dir (* 2 pi))
  523.                                     (- dir (* 2 pi))
  524.                                     dir
  525.                                   )
  526.                         )
  527.                         (if (equal dir
  528.                                    (setq dir (angle (trans (dl_val 10 tmp) 
  529.                                                            (dl_val -1 tmp) 
  530.                                                            1)
  531.                                                     strtpt
  532.                                              ) 
  533.                                    )
  534.                                    0.01)
  535.                           (- dir (/ pi 2))
  536.                           (+ dir (/ pi 2))
  537.                         )
  538.                       )
  539.                     )
  540.           )
  541.           (command "arc" 
  542.                    strtpt 
  543.                    "e" 
  544.                    nextpt 
  545.                    "d"
  546.                    (* dir (/ 180 pi))
  547.           )
  548.           ;; Close with arc segments
  549.           (dl_mlf 4)
  550.         )
  551.       )
  552.       ;; set nextpt to "CLose" which will cause an exit.
  553.       (setq nextpt "CLose"
  554.             v:stpt nil
  555.             cont   nil
  556.       )
  557.     )
  558.   )
  559. )
  560. ;;;
  561. ;;; A point was entered, do either an arc or line segment.
  562. ;;;
  563. ;;; dl_ds == DLine_Do_Segment
  564. ;;;
  565. (defun dl_ds ()
  566.   (if (equal strtpt nextpt 0.0001)
  567.     (progn
  568.       (princ "\nCoincident point -- please try again. ")
  569.       (if dl_arc
  570.         (setq nextpt "Arc")
  571.         (setq nextpt "Line")
  572.       )
  573.     )
  574.     (progn
  575.       (command "undo" "group")
  576.       (setq nextpt (list (car nextpt) (cadr nextpt) (caddr strtpt)))
  577.       (if dl_arc
  578.         (progn
  579.           (command "arc" strtpt nextpt)
  580.           (prompt "\nEndpoint: ")
  581.           (command pause)
  582.           (setq nextpt (getvar "lastpoint")
  583.                 v:stpt nextpt)
  584.           (setq temp (entlast))
  585.           ;; Delete the last arc segment so we can find the line or 
  586.           ;; arc under it.
  587.           (entdel temp)
  588.           (if dl:snp
  589.             (dl_ved "brk_e2" nextpt)
  590.           )
  591.           ;; Restore the arc previously deleted.
  592.           (entdel temp)
  593.           ;; Draw the arc segments.
  594.           (dl_mlf 2)
  595.         )
  596.         (progn
  597.           (setq v:stpt nextpt)
  598.           (if dl:snp
  599.             (dl_ved "brk_e2" nextpt)
  600.           )
  601.           (if (and brk_e1 (eq brk_e1 brk_e2) (= (dl_val 0 brk_e1) "LINE"))
  602.             (progn
  603.               (princ "\nSecond point cannot be on the same line segment. ")
  604.               (setq brk_e2 nil)
  605.             )
  606.             ;; Draw the line segments.
  607.             (dl_mlf 1)
  608.           )
  609.         )
  610.       )
  611.       (if brk_e2 (setq nextpt "Quit"))
  612.     )
  613.   )
  614. )
  615. ;;;
  616. ;;; The CEnter option for drawing arc segments was selected.
  617. ;;;
  618. ;;; dl_ceo == DLine_CEnter_Option
  619. ;;;
  620. (defun dl_ceo ()
  621.   (command "undo" "group")
  622.   (setq temp T)
  623.   (while temp
  624.     (initget 1)
  625.     (setq cpt (getpoint strtpt "\nCenter point: "))
  626.     (if (<= (distance cpt strtpt) (- (/ (getvar "tracewid") 2.0) dl:osd))
  627.       (progn
  628.         (princ 
  629.         "\nThe radius defined by the selected center point is too small ")
  630.         (princ "\nfor the current Dline width.  ")
  631.         (princ "Please select another point.")
  632.       )
  633.       (setq temp nil)
  634.     )
  635.   )
  636.   ;; Start the ARC command so that we can get visual dragging.
  637.   (command "arc" strtpt "c" cpt)
  638.   (initget "Angle Length Endpoint")
  639.   (setq nextpt (getkword "\nAngle/Length of chord/<Endpoint>: "))
  640.   (cond 
  641.     ((= nextpt "Angle")
  642.       (prompt "\nIncluded angle: ")
  643.       (command "a" pause)
  644.       (setq nextpt (dl_vnp)
  645.             v:stpt nextpt
  646.       )
  647.       ;; Draw the arc segments.
  648.       (dl_mlf 2) 
  649.     )
  650.     ((= nextpt "Length")
  651.       (prompt "\nChord length: ")
  652.       (command "l" pause)
  653.       (setq nextpt (dl_vnp)
  654.             v:stpt nextpt
  655.       )
  656.       ;; Draw the arc segments.
  657.       (dl_mlf 2) 
  658.     )
  659.     (T
  660.       (prompt "\nEndpoint: ")
  661.       (command pause)
  662.       (setq nextpt (dl_vnp)
  663.             v:stpt nextpt
  664.       )
  665.       ;; Draw the arc segments.
  666.       (dl_mlf 2) 
  667.     )
  668.   )
  669. )
  670. ;;;
  671. ;;; Endpoint option was selected.
  672. ;;;
  673. ;;; dl_epo == DLine_End_Point_Option
  674. ;;;
  675. (defun dl_epo ()
  676.   (command "undo" "group")
  677.   (initget 1)
  678.   (setq cpt (getpoint "\nEndpoint: "))
  679.   ;; Start the ARC command so that we can get visual dragging.
  680.   (command "arc" strtpt "e" cpt)
  681.   (initget "Angle Direction Radius Center")
  682.   (setq nextpt (getkword "\nAngle/Direction/Radius/<Center>: "))
  683.   (cond 
  684.     ((= nextpt "Angle")
  685.       (prompt "\nIncluded angle: ")
  686.       (command "a" pause)
  687.       (setq nextpt (dl_vnp)
  688.             v:stpt nextpt
  689.       )
  690.       ;; Draw the arc segments.
  691.       (dl_mlf 2) 
  692.     )
  693.     ((= nextpt "Direction")
  694.       (prompt "\nTangent direction: ")
  695.       (command "d" pause)
  696.       (setq nextpt (dl_vnp)
  697.             v:stpt nextpt
  698.       )
  699.       ;; Draw the arc segments.
  700.       (dl_mlf 2) 
  701.     )          
  702.     ((= nextpt "Radius")
  703.       (setq temp T)
  704.       (while temp
  705.         (initget 1)
  706.         (setq rad (getdist cpt "\nRadius: "))
  707.         
  708.         (if (or (<= rad (/ (getvar "tracewid") 2.0))
  709.                 (< rad (/ (distance strtpt cpt) 2.0)))
  710.           (progn
  711.             (princ "\nThe radius entered is less than 1/2 ")
  712.             (princ "of the Dline width or is invalid")
  713.             (princ "\nfor the selected endpoints.  ")
  714.             (princ "Please enter a radius greater than ")
  715.             (if (< (/ (getvar "tracewid") 2.0) 
  716.                    (/ (distance strtpt cpt) 2.0))
  717.               (princ (rtos (/ (distance strtpt cpt) 2.0)))
  718.               (princ (rtos (/ (getvar "tracewid") 2.0)))
  719.             )
  720.             (princ ". ")
  721.           )
  722.           (setq temp nil)
  723.         )
  724.       )
  725.       (command "r" rad)
  726.       (setq nextpt (dl_vnp)
  727.             v:stpt nextpt
  728.       )
  729.       ;; Draw the arc segments.
  730.       (dl_mlf 2) 
  731.     )
  732.     (T
  733.       (prompt "\nCenter: ")
  734.       (command pause)
  735.       (setq nextpt (dl_vnp)
  736.             v:stpt nextpt
  737.       )
  738.       ;; Draw the arc segments.
  739.       (dl_mlf 2) 
  740.     )
  741.   )
  742. )
  743. ;;;
  744. ;;; Set the ending save points for capping the DLINE.
  745. ;;;
  746. ;;; dl_ssp == DLine_Set_Save_Points
  747. ;;;
  748. (defun dl_ssp ( / temp)
  749.   (setq temp (length savpts))
  750.   (if (> temp 1)
  751.     (progn
  752.       (setq savpt3 (nth (- temp 2) savpts)
  753.             savpt4 (nth (- temp 1) savpts)
  754.       )
  755.     )
  756.   )
  757. )
  758. ;;;
  759. ;;; Set the alignment of the "ghost" line to one of the following values:
  760. ;;;   
  761. ;;;   Left   == -1/2 of width (Real number)
  762. ;;;           > -1/2 of width (Real number)
  763. ;;;   Center == 0.0
  764. ;;;           < +1/2 of width (Real number)
  765. ;;;   Right  == +1/2 of width (Real number)
  766. ;;;
  767. ;;; All of the alignment options are taken as if you are standing at the
  768. ;;; start point of the line or arc looking toward the end point, with 
  769. ;;; left and negative values being on the left, center or 0.0 being
  770. ;;; directly in line, and right or positive on the right.
  771. ;;; 
  772. ;;; Entering a real number equal to 1/2 of the width sets an absolute offset
  773. ;;; distance from the centerline, while specifying the same offset distance
  774. ;;; with the keywords tells the routine to change the offset distance to 
  775. ;;; match 1/2 of the width, whenever it is changed.
  776. ;;;
  777. ;;; NOTE:  If you wish to allow the dragline to be positioned outside
  778. ;;;      of the two arcs or lines being created, you may set the local 
  779. ;;;      variable "dragos" = T, on the 4th line of the defun, which  
  780. ;;;      checks that the offset value entered is not greater or less 
  781. ;;;      than + or - TRACEWID / 2.
  782. ;;;      
  783. ;;;      You should be aware that the results of allowing this to occur
  784. ;;;      may not be obvious or necessarily correct.  Specifically, when
  785. ;;;      drawing lines with a width of 1 and an offset of 4, if you draw
  786. ;;;      segments as follows, the lines will cross back on themselves.
  787. ;;;      
  788. ;;;      dl 0,0,0 10,0,0 10,5 then 5,5
  789. ;;;      
  790. ;;;      However, this can be quite useful for creating parallel DLINE's.
  791. ;;;      
  792. ;;; dl_sao == DLine_Set_Alignment_Option
  793. ;;;
  794. (defun dl_sao (/ temp dragos)
  795.   (initget "Left Center Right")
  796.   (setq temp dl:osd)
  797.   ;;(setq dragos T)                   ; See note above.
  798.   (setq dl:osd (getreal (strcat
  799.     "\nSet dragline position to Left/Center/Right/<Offset from center = "
  800.     (rtos dl:osd) ">: ")))
  801.   (cond
  802.     ((= dl:osd "Left")
  803.       (setq dl:aln 1
  804.             dl:osd (- (/ (getvar "tracewid") 2.0))
  805.       )
  806.     )
  807.     ((= dl:osd "Center")
  808.       (setq dl:aln 0
  809.             dl:osd 0.0
  810.       )
  811.     )
  812.     ((= dl:osd "Right")
  813.       (setq dl:aln 2
  814.             dl:osd (/ (getvar "tracewid") 2.0)
  815.       )
  816.     )
  817.     ((= (type dl:osd) 'REAL)
  818.       (if dragos
  819.         (setq dl:aln nil)
  820.         (progn
  821.           (setq dl:aln nil)
  822.           (if (> dl:osd (/ (getvar "tracewid") 2.0))
  823.             (progn
  824.               (princ "\nValue entered is out of range.  Reset to ")
  825.               (princ (/ (getvar "tracewid") 2.0))
  826.               (setq dl:osd (/ (getvar "tracewid") 2.0))
  827.             )
  828.           )
  829.           (if (< dl:osd (- (/ (getvar "tracewid") 2.0)))
  830.             (progn
  831.               (princ "\nValue entered is out of range.  Reset to ")
  832.               (princ (- (/ (getvar "tracewid") 2.0)))
  833.               (setq dl:osd (- (/ (getvar "tracewid") 2.0)))
  834.             )
  835.           )
  836.         )
  837.       )
  838.     )
  839.     (T
  840.       (setq dl:osd temp)
  841.     )
  842.   )
  843. )
  844. ;;;
  845. ;;; Set a new DLINE width.
  846. ;;;
  847. ;;; dl_snw == DLine_Set_New_Width
  848. ;;;
  849. (defun dl_snw ()
  850.   (initget 6)
  851.   (setvar "tracewid"
  852.     (if (setq temp (getdist (strcat 
  853.       "\nNew DLINE width <" (rtos (getvar "tracewid")) ">: ")))
  854.       temp
  855.       (getvar "tracewid") 
  856.     ) 
  857.   )
  858.   (if dl:aln
  859.     (cond
  860.       ((= dl:aln 1) ; left aligned
  861.         (setq dl:osd (- (/ (getvar "tracewid") 2.0)))
  862.       )
  863.       ((= dl:aln 2) ; right aligned
  864.         (setq dl:osd (/ (getvar "tracewid") 2.0))
  865.       )
  866.       (T
  867.         (princ)     ; center aligned
  868.       )
  869.     )
  870.   )
  871. )
  872. ;;;
  873. ;;; Get an offset from a given point to the start point toward a second
  874. ;;; point.  The distance between the two points is the default, but any
  875. ;;; positive distance may be entered.  If a negative number is entered,
  876. ;;; it is used as a percentage distance from the "Offset from" point 
  877. ;;; toward the "Offset toward" point, i.e., if -75 is entered, a point
  878. ;;; 75% of the distance between the two points listed above is returned.
  879. ;;; 
  880. ;;;
  881. ;;; dl_ofs == DLine_OFfset_Startpoint
  882. ;;;
  883. (defun dl_ofs ()
  884.   (menucmd "s=osnapb")
  885.   (initget 1)
  886.   (setq strtpt (getpoint "\nOffset from: "))
  887.   (initget 1)
  888.   (setq nextpt (getpoint strtpt "\nOffset toward: "))
  889.   
  890.   (setq dist (getdist strtpt (strcat
  891.     "\nEnter the offset distance <" (rtos (distance strtpt nextpt)) 
  892.     ">: ")))
  893.   (setq dist (if (or (= dist "") (null dist))
  894.                (distance strtpt nextpt)
  895.                (if (< dist 0)
  896.                  (* (distance strtpt nextpt) (/ (abs dist) 100.0))
  897.                  dist
  898.                )
  899.              )
  900.   )              
  901.   (setq strtpt (polar strtpt
  902.                       (angle strtpt nextpt)
  903.                       dist
  904.                ) 
  905.   )
  906.   (setq temp nil)
  907.   (command "undo" "group")
  908. )
  909. ;;;
  910. ;;; Set snap options to ON, OFF or set the size of the area to be searched
  911. ;;; by (ssget point) via "pickbox".  This value is being limited for built-
  912. ;;; in display drivers at 10 pixels.  For ADI drivers it may be necessary 
  913. ;;; to bump up this number by adjusting "MAXSNP" at the top of this file.
  914. ;;;
  915. ;;; dl_sso == DLine_Set_Snap_Options
  916. ;;;
  917. (defun dl_sso ()
  918.   (initget "ON OFf Size")
  919.   (setq ans (getkword
  920.     "\nSet snap size or snap On/Off.  Size/OFF/<ON>: "))
  921.   (if (= ans "OFf") 
  922.     (progn
  923.       (setq dl:snp nil)
  924.       (setvar "pickbox" 0) 
  925.     )
  926.     (if (= ans "Size") 
  927.       (progn
  928.         (setq dl:snp T ans 0)
  929.         (while (or (< ans 1) (> ans MAXSNP))
  930.           (setq ans (getint (strcat
  931.             "\nNew snap size (1 - " (itoa MAXSNP) ") <" (itoa dl:opb) ">: ")))
  932.  
  933.           (if (or (= ans "") (null ans))
  934.             (setq ans dl:opb)
  935.           )
  936.         )
  937.         (setvar "pickbox" ans)
  938.         (setq dl:opb ans)
  939.       )
  940.       (progn
  941.         (setq dl:snp T)
  942.         (setvar "pickbox" dl:opb)
  943.       )  
  944.     ) 
  945.   )
  946.   (if dl:snp
  947.     (if (= uctr 0)
  948.       (dl_ved "brk_e1" strtpt)
  949.     ) 
  950.   ) 
  951.   (if dl_arc
  952.     (setq nextpt "Arc")
  953.     (setq nextpt "Line")
  954.   )
  955.  
  956. )
  957. ;;;
  958. ;;; Obtain and verify the extrusion direction of an entity at the 
  959. ;;; start point or endpoint of the line or arc we are drawing.
  960. ;;;
  961. ;;; dl_ved == DLine_Verify_Extrusion_Direction
  962. ;;;
  963. (defun dl_ved (vent pt)
  964.   ;; Get entity to break if the user snapped to a DLINE.
  965.   ;; Make sure that it is a line or arc and that its extrusion
  966.   ;; direction is parallel to the current UCS.
  967.   (if (set (read vent) (ssget pt))
  968.     (progn
  969.       (set (read vent) (ssname (eval (read vent)) 0))
  970.       (if (and 
  971.             (or (= (dl_val 0 (eval (read vent))) "ARC")
  972.                 (= (dl_val 0 (eval (read vent))) "LINE")
  973.             )
  974.             (equal (caddr(dl_val 210 (eval (read vent))))
  975.                    (caddr(trans '(0 0 1) 1 0)) 0.001)
  976.           )
  977.         (princ)
  978.         (progn
  979.           (princ (strcat
  980.             "\nEntity found is not an arc or line, "
  981.             "or is not parallel to the current UCS. "))
  982.           (set (read vent) nil)
  983.         )
  984.       )
  985.     )
  986.   )
  987.   (eval (read vent))
  988. )
  989. ;;;
  990. ;;; Verify nextpt.
  991. ;;; Get the point on the arc at the opposite 
  992. ;;; end from the start point (strtpt).
  993. ;;;
  994. ;;; dl_vnp == DLine_Verify_NextPt
  995. ;;;
  996. (defun dl_vnp (/ temp cpt ang rad)
  997.  
  998.   (setq temp (entlast))
  999.   (if (= (dl_val 0 temp) "LINE")
  1000.     (setq nextpt (if (equal strtpt (dl_val 10 temp) 0.001)
  1001.                    (dl_val 11 temp)
  1002.                    (dl_val 10 temp)
  1003.                  )
  1004.     )
  1005.     ;; Then it must be an arc...
  1006.     (progn
  1007.       ;; get its center point
  1008.       (setq cpt  (trans (dl_val 10 temp) (dl_val -1 temp) 1)
  1009.             ang  (dl_val 50 temp)     ; starting angle
  1010.             rad  (dl_val 40 temp)     ; radius
  1011.       )
  1012.       (setq ange (trans '(1 0 0) (dl_val -1 temp) 1)
  1013.             ange (angle '(0 0 0) ange)
  1014.             ang (+ ang ange)
  1015.       )
  1016.       (if (> ang (* 2 pi))
  1017.         (setq ang (- ang (* 2 pi)))
  1018.       )
  1019.       (setq nextpt (if (equal strtpt (polar cpt ang rad) 0.01)
  1020.                      (polar cpt (dl_val 51 temp) rad)
  1021.                      (polar cpt ang rad)
  1022.                    )
  1023.       )
  1024.     )
  1025.   )
  1026. )
  1027. ;;; ----------------- Main Line Drawing Function -------------------
  1028. ;;;
  1029. ;;; Draw the lines.
  1030. ;;;
  1031. ;;; dl_mlf == DLine_Main_Line_Function
  1032. ;;;
  1033. (defun dl_mlf (flg / temp1 temp2 newang ang1 ang2 
  1034.                      ent cpt ang rad1 rad2 sent1 sent2
  1035.                      tmpt1 tmpt2 tmpt3 tmpt4)
  1036.  
  1037.   ;; Verify nextpt
  1038.   (if (null nextpt) (setq nextpt (dl_vnp)))
  1039.   
  1040.   (if (equal nextpt (nth 0 spts) 0.01)
  1041.     (if dl_arc
  1042.       (setq flg 4)
  1043.       (setq flg 3)
  1044.     )
  1045.   )
  1046.    
  1047.   (setq temp1  (+ (/ (getvar "tracewid") 2.0) dl:osd)
  1048.         temp2  (- (getvar "tracewid") temp1)
  1049.         newang (angle strtpt nextpt)
  1050.         ang1   (+ (angle strtpt nextpt) (/ pi 2))
  1051.         ang2   (- (angle strtpt nextpt) (/ pi 2))
  1052.   )
  1053.   (cond
  1054.     ((= flg 1)                        ; if drawing lines
  1055.       (dl_dls nil ang1 temp1)         ; Draw line segment 1
  1056.       (dl_dls nil ang2 temp2)         ; Draw line segment 2
  1057.     )
  1058.     ((or (= flg 2) (= flg 4))         ; else drawing arcs...
  1059.       (setq tmp (entlast)             ; get the last arc entity
  1060.             ent  (entget tmp)         ; (i.e., the guideline)
  1061.             ;; get its center point
  1062.             cpt  (trans (dl_val 10 tmp) (dl_val -1 tmp) 1) 
  1063.             ang  (dl_val 50 tmp)      ; starting angle
  1064.       )
  1065.       (setq ange (trans '(1 0 0) (dl_val -1 tmp) 1)
  1066.             ange (angle '(0 0 0) ange)
  1067.             ang (+ ang ange)
  1068.       )
  1069.       (if (> ang (* 2 pi))
  1070.         (setq ang (- ang (* 2 pi)))
  1071.       )
  1072.      
  1073.       ;; if start angle needs revision
  1074.       (if (equal (angle cpt strtpt) ang 0.01)   
  1075.         (progn
  1076.           ;; Start angle needs revision.
  1077.           (setq strt_a T
  1078.                 rad1  (+ (dl_val 40 tmp) temp2) ; outer radius
  1079.                 rad2  (- (dl_val 40 tmp) temp1) ; inner radius
  1080.           )
  1081.           (setq ent (subst (cons 40 rad2) ; modify its radius
  1082.                            (assoc 40 ent) 
  1083.                            ent))
  1084.           (entmod ent) 
  1085.           (dl_atl)                    ; Add ename to list
  1086.           (setq save_1 ent)
  1087.           (setq sent1 (dl_val -1 tmp))                            
  1088.           (if (= flg 4)
  1089.             (if (> uctr 2)
  1090.               (dl_das 0 rad2 50)      ; modify arc endpt and close
  1091.             )
  1092.             (dl_das nil rad2 50)      ; else modify arc endpt
  1093.           )
  1094.           ;; Create the "parallel" arc
  1095.           (command "offset" (getvar "tracewid") ; offset the arc
  1096.                             (list tmp '(0 0 0)) 
  1097.                             (polar cpt ang (+ 1 rad1 rad2))
  1098.                             "")
  1099.           (setq tmp (entlast)         ; get the offset arc
  1100.                 ent  (entget tmp))
  1101.           (dl_atl)                    ; Add ename to list
  1102.           (setq save_2 ent)
  1103.           (setq sent2 tmp) 
  1104.           (if (= flg 4)
  1105.             (if (> uctr 3)
  1106.               (progn
  1107.                 (dl_das 1 rad1 50)    ; modify arc endpt and close
  1108.  
  1109.                 ;; set nextpt to "CLose" which will cause an exit.
  1110.                 (setq nextpt "CLose"
  1111.                       v:stpt nil
  1112.                       cont   nil
  1113.                 )
  1114.               )
  1115.             )
  1116.             (dl_das nil rad1 50)      ; else modify arc endpt
  1117.           )
  1118.  
  1119.         )
  1120.         (progn                        ; if end angle needs revision
  1121.           ;; End angle needs revision.
  1122.           (setq strt_a nil
  1123.                 rad1  (+ (dl_val 40 tmp) temp1) ; outer radius
  1124.                 rad2  (- (dl_val 40 tmp) temp2) ; inner radius
  1125.           )
  1126.           (setq ent (subst (cons 40 rad1) ; modify its radius
  1127.                            (assoc 40 ent) 
  1128.                            ent))
  1129.           (entmod ent)                             
  1130.           (dl_atl)                    ; Add ename to list
  1131.           (setq save_1 ent)
  1132.           (setq sent1 (dl_val -1 tmp))                            
  1133.           (if (= flg 4)
  1134.             (if (> uctr 2)
  1135.               (dl_das 0 rad1 51)      ; modify arc endpt and close
  1136.             )
  1137.             (dl_das nil rad1 51)      ; else modify arc endpt
  1138.           )
  1139.           ;; Create the "parallel" arc
  1140.           (command "offset" (getvar "tracewid")    
  1141.                             (list tmp '(0 0 0)) 
  1142.                             cpt 
  1143.                             "")
  1144.           (setq tmp (entlast)         ; get the last arc entity
  1145.                 ent  (entget tmp))
  1146.           (dl_atl)                    ; Add ename to list
  1147.           (setq save_2 ent)
  1148.           (setq sent2 tmp)
  1149.           (if (= flg 4)
  1150.             (if (> uctr 3)
  1151.               (progn
  1152.                 (dl_das 1 rad2 51)    ; modify arc endpt and close
  1153.  
  1154.                 ;; set nextpt to "CLose" which will cause an exit.
  1155.                 (setq nextpt "CLose"
  1156.                       v:stpt nil
  1157.                       cont   nil
  1158.                 )
  1159.               )
  1160.             )
  1161.             (dl_das nil rad2 51)      ; else modify arc endpt
  1162.           )
  1163.         )
  1164.       )
  1165.  
  1166.     )
  1167.     ((= flg 3)                        ; if straight closing
  1168.       (setq nextpt (nth 0 spts)
  1169.             ang1   (+ (angle strtpt nextpt) (/ pi 2))
  1170.             ang2   (- (angle strtpt nextpt) (/ pi 2))
  1171.       )
  1172.       (dl_dls 0 ang1 temp1)
  1173.       (dl_dls 1 ang2 temp2)
  1174.  
  1175.       ;; set nextpt to "CLose" which will cause an exit.
  1176.       (setq nextpt "CLose"
  1177.             v:stpt nil
  1178.             cont   nil
  1179.       )
  1180.     )
  1181.     (T
  1182.       (princ "\nERROR:  Value out of range. ")
  1183.       (exit)
  1184.     )
  1185.   )
  1186.   (setq strtpt nextpt   
  1187.         spts   (append spts (list strtpt))
  1188.         savpts (append savpts (list savpt3))
  1189.         savpts (append savpts (list savpt4))
  1190.   )
  1191.   (command "undo" "e")                ; only end when DLINE's have been drawn
  1192. )
  1193. ;;; ------------------- End Support Functions -----------------------
  1194. ;;; ---------------- Begin Line Drawing Functions -------------------
  1195. ;;;
  1196. ;;; Straight DLINE function
  1197. ;;;
  1198. ;;; dl_dls == DLine_Draw_Line_Segment
  1199. ;;;
  1200. (defun dl_dls (flgn ang temp / j k pt1 pt2 tmp1 ent1 p1 p2)
  1201.  
  1202.   (mapcar                             ; get endpoints of the offset line
  1203.     '(lambda (j k)
  1204.        (set j (polar (eval k) ang temp))
  1205.      )      
  1206.      '(pt1 pt2)
  1207.      '(strtpt nextpt)
  1208.   )
  1209.   (cond
  1210.     ((= uctr 0)
  1211.       ;; Set points 1 and 2 for segment 1.
  1212.       (setq p1 (if (dl_l01 brk_e1 "1" pt1 pt2 strtpt) ipt savpt1)) 
  1213.       (setq pt2 (if (dl_l01 brk_e2 "3" pt2 pt1 nextpt) ipt savpt3))
  1214.       (setq pt1 p1)
  1215.     )
  1216.     ((= uctr 1)
  1217.       ;; Set points 1 and 2 for segment 2.
  1218.       (setq p1 (if (dl_l01 brk_e1 "2" pt1 pt2 strtpt) ipt savpt2))
  1219.       (setq pt2 (if (dl_l01 brk_e2 "4" pt2 pt1 nextpt) ipt savpt4))
  1220.       (setq pt1 p1)
  1221.       
  1222.       ;; Now break the line or arc found at the start point 
  1223.       ;; if there is one, and we are in a breaking mood.
  1224.       (if (and dl:brk brk_e1)
  1225.         (progn
  1226.           (command "break" brk_e1 savpt1 savpt2)
  1227.         )
  1228.       )
  1229.       ;; Now break the line or arc found at the end point 
  1230.       ;; if there is one, and we are in a breaking mood.
  1231.       (if (and dl:brk brk_e2)
  1232.         (progn
  1233.           (if (eq brk_e1 brk_e2)
  1234.             (progn
  1235.               ;; Delete first line so we can find the arc or line that
  1236.               ;; we found previously.
  1237.               (entdel (nth 0 wnames))  
  1238.               (dl_ved "brk_e2" nextpt)
  1239.               ;; Restore first line
  1240.               (entdel (nth 0 wnames))
  1241.             )
  1242.           )
  1243.           (command "break" brk_e2 savpt3 savpt4)
  1244.         )
  1245.       )
  1246.       ;; Do not set brk_e2 nil... it will be set later.
  1247.     )
  1248.     ((= (rem uctr 2.0) 0)    
  1249.       (setq fang nil)
  1250.       (setq p1 (dl_dl2 pt1))          ; Draw line part 2
  1251.       (setq pt2 (if (dl_l01 brk_e2 "3" pt2 pt1 strtpt) 
  1252.                   ipt
  1253.                   savpt3
  1254.                 )
  1255.       )
  1256.       (setq pt1 p1)
  1257.       (if flgn                        ; if closing
  1258.         (progn
  1259.           (setq tmp1 (nth flgn wnames)
  1260.                 ent1 (entget tmp1)    ; get the corresponding prev. entity
  1261.           )
  1262.           (if (= (dl_val 0 tmp1) "LINE")
  1263.             ;; if it's a line
  1264.             (setq pt2 (dl_mls nil 10))           
  1265.             ;; if it's an arc
  1266.             (setq pt2 (dl_mas T nil pt2 pt1 nil))  
  1267.           )
  1268.         )                             
  1269.       )
  1270.     )
  1271.     (T
  1272.       (setq p1 (dl_dl2 pt1))              ; Draw line part 2
  1273.       (setq pt2 (if (dl_l01 brk_e2 "4" pt2 pt1 nextpt) 
  1274.                   ipt
  1275.                   savpt4
  1276.                 )
  1277.       )
  1278.       (setq pt1 p1)
  1279.       (if flgn                        ; if closing
  1280.         (progn
  1281.           (setq tmp1 (nth flgn wnames)
  1282.                 ent1 (entget tmp1)    ; get the corresponding prev. entity
  1283.                 brk_e1 nil
  1284.                 brk_e2 nil
  1285.           )
  1286.           (if (= (dl_val 0 tmp1) "LINE")
  1287.             ;; if it's a line
  1288.             (setq pt2 (dl_mls nil 10))           
  1289.             ;; if it's an arc
  1290.             (setq pt2 (dl_mas T nil pt2 pt1 nil))  
  1291.           )
  1292.         )                             
  1293.       )
  1294.       ;; Now break the line or arc found at the end point 
  1295.       ;; if there is one, and we are in a breaking mood.
  1296.       (if (and dl:brk brk_e2)
  1297.         (progn
  1298.           (command "break" brk_e2 savpt3 savpt4)
  1299.         )
  1300.       )
  1301.       ;; Do not set brk_e2 nil... it will be set later.
  1302.     )
  1303.   )
  1304.   (command "line" pt1 pt2 "")         ; draw the line
  1305.   (setq wnames (if (null wnames) 
  1306.                  (list (setq elast (entlast)) )
  1307.                  (append wnames (list (setq elast (entlast)))))
  1308.         uctr   (1+ uctr)
  1309.   )
  1310.   wnames
  1311. )
  1312. ;;;
  1313. ;;; Set pt1 or pt2 based on whether there is an arc or line to be broken.
  1314. ;;;
  1315. ;;; dl_l01 == DLine_draw_Lines_0_and_1
  1316. ;;;
  1317. (defun dl_l01 (bent1 n p1 p2 pt / temp)
  1318.   (setq n (strcat "savpt" n))
  1319.   (setq spt nil)
  1320.   (if bent1
  1321.     (if (= (dl_val 0 bent1) "LINE")
  1322.       (progn
  1323.         (setq temp (inters (trans (dl_val 10 bent1) 0 1)
  1324.                             (trans (dl_val 11 bent1) 0 1)
  1325.                             p1
  1326.                             p2
  1327.                             nil
  1328.                     )
  1329.         ) 
  1330.         (if temp
  1331.           (set (read n) temp)
  1332.           (progn
  1333.             (set (read n) p1)
  1334.             (setq brk_e1 nil)
  1335.           )
  1336.         )
  1337.       )
  1338.       (progn
  1339.         (set (read n) (dl_ial bent1 p1 p2 pt))
  1340.         ;; Spt is set only if there was no intersection point.
  1341.         (if spt
  1342.           (progn
  1343.             (setq ipt (eval (read n)))
  1344.             (set (read n) spt)
  1345.           )
  1346.         )
  1347.       )
  1348.     )
  1349.     (set (read n) p1)
  1350.   )
  1351.   (if spt
  1352.     T
  1353.     nil
  1354.   )
  1355. )
  1356. ;;;
  1357. ;;; Do more of the line drawing stuff.  This is where we call the modify 
  1358. ;;; functions for the previous arc or line segment.  The line end being
  1359. ;;; modified is always the group 11 end, but we have to test the start
  1360. ;;; and end angle of an arc to tell which end to modify.
  1361. ;;;
  1362. ;;; dl_dl2 == DLine_Draw_Line_segment_part_2
  1363. ;;;
  1364. (defun dl_dl2 (npt)
  1365.   (setq tmp1 (nth (- uctr 2) wnames)
  1366.         ent1 (entget tmp1))           ; get the corresponding prev. entity
  1367.    
  1368.   (if (= (dl_val 0 tmp1) "LINE")  
  1369.     ;; Check angles 0 180, -180  and 360...   
  1370.     (if (or  (equal (angle strtpt nextpt)
  1371.                    (angle (trans (dl_val 10 tmp1) 0 1)
  1372.                           (trans (dl_val 11 tmp1) 0 1)) 0.001)
  1373.              (equal (angle strtpt nextpt)
  1374.                    (angle (trans (dl_val 11 tmp1) 0 1)
  1375.                           (trans (dl_val 10 tmp1) 0 1)) 0.001)
  1376.              (equal (+ (* 2 pi) (angle strtpt nextpt))
  1377.                    (angle (trans (dl_val 10 tmp1) 0 1)
  1378.                           (trans (dl_val 11 tmp1) 0 1)) 0.001)
  1379.         )
  1380.       ;; if it's a line
  1381.       (progn
  1382.         (setq brk_e2 nil)
  1383.         (command "line" (trans (dl_val 11 tmp1) 0 1) pt1 "") 
  1384.         pt1 
  1385.       )
  1386.       ;; else, if it's an arc
  1387.       (progn
  1388.         (dl_mls nil 11)
  1389.       )
  1390.     )
  1391.     ;; if it's an arc
  1392.     (dl_mas nil nil pt1 pt2 strtpt)  
  1393.   )
  1394. )
  1395. ;;;
  1396. ;;; Modify line endpoint
  1397. ;;;
  1398. ;;; dl_mls == DLine_Modify_Line_Segment
  1399. ;;;
  1400. (defun dl_mls (flg2 nn / spt ept pt)  ; flg2 = nil if line to line
  1401.                                       ;      = T   if line to arc
  1402.  
  1403.   ;; This is the previous entity; a line
  1404.   (setq spt (trans (dl_val 10 tmp1) 0 1)   
  1405.         ept (trans (dl_val 11 tmp1) 0 1)
  1406.   )
  1407.   (if flg2
  1408.     ;; find intersection with arc; tmp == ename of arc
  1409.     (progn
  1410.       ;; Find arc intersection with line; tmp == ename of arc.
  1411.       (setq pt (dl_ial tmp spt ept (if flgn nextpt strtpt)))
  1412.     )
  1413.  
  1414.     ;; find intersection with line
  1415.     (setq pt (inters spt ept pt1 pt2 nil)) 
  1416.   )
  1417.   ;; modify the previous line
  1418.   (if pt 
  1419.     (entmod (subst (cons nn (trans pt 1 0)) 
  1420.                    (assoc nn ent1) 
  1421.                    ent1))
  1422.     (setq pt pt2)
  1423.   )
  1424.   pt
  1425. )
  1426. ;;; 
  1427. ;;; This routine does a variety of tasks: it calculate the distance from
  1428. ;;; the center of the arc (or congruent circle) to a line, then it
  1429. ;;; calculates up to two intersection points of a line and the arc,
  1430. ;;; then it attempts to determine which of the points serves as a 
  1431. ;;; best-fit to the following criteria:
  1432. ;;; 
  1433. ;;;   1) One end of the arc must lie "on" the line, or
  1434. ;;;      one end of the line must lie on the arc. 
  1435. ;;;   2) Given that the point given in 1 above is p1,
  1436. ;;;      and that the other point is p2, then if the arc crosses over
  1437. ;;;      the line then use p2, otherwise the arc does not cross over
  1438. ;;;      the line so use p1.
  1439. ;;;      
  1440. ;;; If the line and the arc do not intersect, then a line will be drawn
  1441. ;;; from the point of intersection of the arc and the perpendicular from
  1442. ;;; the line to the arc centerpoint, and the line;  The line and arc will be 
  1443. ;;; trimmed or extended as needed to meet these points.
  1444. ;;; 
  1445. ;;; If the line and arc are tangent, then the arc and line are
  1446. ;;; trimmed/extended to this point. 
  1447. ;;;
  1448. ;;; p1 and p2 are two points on a line
  1449. ;;; ename  == entity name of arc
  1450. ;;; flg == T when the segment being drawn ends on an arc, 
  1451. ;;; flg == nil when the segment being drawn starts on an arc.
  1452. ;;;
  1453. ;;; dl_ial == DLine_Intersect_Arc_with_Line
  1454. ;;;
  1455. (defun dl_ial (arc pt_1 pt_2 npt / d pi2 rad ang nang temp ipt)
  1456.  
  1457.   (setq cpt  (trans (dl_val 10 arc) (dl_val -1 arc) 1)  
  1458.         pi2  (/ pi 2)                 ; 1/2 pi
  1459.         ang  (angle pt_1 pt_2)                   
  1460.         nang (+ ang pi2)              ; Normal to "ang"
  1461.         temp (inters pt_1 pt_2 cpt (polar cpt nang 1) nil)
  1462.         nang (angle cpt temp)
  1463.   )
  1464.   ;; Get the perpendicular distance from the center of the arc to the line.
  1465.   (setq d (distance cpt temp))
  1466.  
  1467.   (cond
  1468.     ((equal (setq rad (dl_val 40 arc)) d 0.01)
  1469.       ;; One intersection.
  1470.       (setq ipt temp)
  1471.     )
  1472.     ((< rad d)                       
  1473.       ;; No intersection.
  1474.       (setq spt (polar cpt nang rad)
  1475.             ipt temp
  1476.       )
  1477.       (command "line" spt ipt "")
  1478.       ipt
  1479.     )
  1480.     (T
  1481.       ;; Two intersections. Now...
  1482.       ;; If drawing arcs, fang is set, we're past the first segment...
  1483.       ;; Reset the `near' point based on the previous ipt.  This can be
  1484.       ;; quite different and necessary from the `npt' passed in.
  1485.       (if (and dl_arc fang (> uctr 1)) 
  1486.         (setq npt (polar cpt fang rad))
  1487.       )
  1488.       (dl_g2p npt)
  1489.       (setq ipt (dl_bp arc pt_1 pt_2 ipt1 ipt2))
  1490.       ;; If `fang' is not set, set it, otherwise set it to nil.
  1491.       (if fang 
  1492.         (setq fang nil)
  1493.         (if dl_arc (setq fang (angle cpt ipt)))
  1494.       )
  1495.       ipt
  1496.     )
  1497.   )
  1498. )
  1499. ;;;
  1500. ;;; Get two intersection points, ordering them such that ipt1
  1501. ;;; is the closer of the two points to the passed-in point "npt".
  1502. ;;;
  1503. ;;; dl_g2p == DLine_Get_2_Points
  1504. ;;;
  1505. (defun dl_g2p (npt / temp l theta)
  1506.   (if (equal d 0.0 0.01)
  1507.     (setq theta pi2
  1508.           nang (+ ang pi2)            ; Normal to "ang"
  1509.     )
  1510.     (setq l     (sqrt (abs (- (expt rad 2) (expt d 2))))
  1511.           theta (abs (atan (/ l d)))
  1512.     )
  1513.   )
  1514.   ;; Get the two angles to the infinite intersection points of the 
  1515.   ;; congruent circle to the arc, and the line, then get the two 
  1516.   ;; intersection points.
  1517.   (setq ipt1 (polar cpt (- nang theta) rad))
  1518.   (setq ipt2 (polar cpt (+ nang theta) rad))
  1519.   ;; Set the closer of the two points to npt to be ipt1.
  1520.   (if (< (distance ipt2 npt) (distance ipt1 npt))
  1521.     ;; Swap points
  1522.     (setq temp ipt1
  1523.           ipt1 ipt2
  1524.           ipt2 temp
  1525.     )
  1526.     (if (equal (distance ipt2 npt) (distance ipt1 npt) 0.01)
  1527.       (exit)
  1528.     )
  1529.   )
  1530.   ipt1
  1531. )
  1532. ;;;
  1533. ;;; Test a point `pt' to see if it is on the line `sp--ep'.
  1534. ;;;
  1535. ;;; dl_onl == DLine_ON_Line_segment
  1536. ;;;
  1537. (defun dl_onl (sp ep pt / cpt sa ea ang)
  1538.   (if (inters sp ep pt
  1539.               (polar pt (+ (angle sp ep) (/ pi 2))
  1540.                      (/ (getvar "tracewid") 10)
  1541.               )
  1542.               T)
  1543.     T 
  1544.     nil
  1545.   )
  1546. )
  1547. ;;;
  1548. ;;; Test a point `pt' to see if it is on the arc `arc'.
  1549. ;;;
  1550. ;;; dl_ona == DLine_ON_Arc_segment
  1551. ;;;
  1552. (defun dl_ona (arc pt / cpt sa ea ang)
  1553.   (setq cpt (trans (dl_val 10 arc) (dl_val -1 arc) 1) 
  1554.         sa  (dl_val 50 arc)           ; angle of current ent start point
  1555.         ea  (dl_val 51 arc)           ; angle of current ent end point
  1556.         ang (angle cpt pt)            ; angle to pt.
  1557.   )
  1558.   (if (> sa ea)
  1559.     (if (or (and (> ang sa) (< ang (+ ea (* 2 pi))))
  1560.             (and (> ang (- ea (* 2 pi))) (< ang ea))
  1561.         ) 
  1562.       T 
  1563.       nil
  1564.     )
  1565.     (if (and (> ang sa) (< ang ea)) T nil)
  1566.   )
  1567. )
  1568. ;;;
  1569. ;;; Get the best intersection point of an arc and a line.  The criteria
  1570. ;;; are as follows:
  1571. ;;; 
  1572. ;;;   1) The best point will lie on both the arc and the line.
  1573. ;;;   2) It will be the point which causes the shortest arc to be created
  1574. ;;;      such that (1) is satisfied.
  1575. ;;;   3) If closing, then always use the point closest to nextpt.  Unless,
  1576. ;;;      the points are equidistant, then use 1 and 2 above to tiebreak.
  1577. ;;;   4) If breaking an arc with a line, always use the points nearest the
  1578. ;;;      break point.
  1579. ;;;
  1580. ;;; dl_bp == DLine_Best_Point_of_arc_and_line
  1581. ;;;
  1582. (defun dl_bp (en1 p1 p2 pp1 pp2 / temp temp1 temp2)
  1583.   (setq temp1 (dl_onl p1 p2 pp2)
  1584.         temp2 (dl_ona en1 pp2)
  1585.         temp  (if (or (= flg 1) (= flg 3)) T nil)
  1586.   )
  1587.   (if (and temp1 temp2)
  1588.     (if (and (< uctr 2) 
  1589.              (and brk_e1 brk_e2))
  1590.       pp1
  1591.       (if (and temp (not fang)) pp1 pp2)
  1592.     )
  1593.     pp1
  1594.   )
  1595. )
  1596. ;;; ----------------- End Line Drawing Functions --------------------
  1597. ;;; ---------------- Begin Arc  Drawing Functions -------------------
  1598. ;;;
  1599. ;;; Draw curved DLINE
  1600. ;;;
  1601. ;;; dl_das == DLine_Draw_Arc_Segment
  1602. ;;;
  1603. (defun dl_das (flgn orad nn / tmp1 ent1 pt ang )
  1604.   (cond
  1605.     ((= uctr 0)
  1606.       (setq sent1 tmp)
  1607.       (dl_a01 brk_e1 "1" strtpt nil)  ; DLine_draw_Arc_0_and_1
  1608.       (dl_a01 brk_e2 "3" nextpt T)    ; DLine_draw_Arc_0_and_1
  1609.     )
  1610.     ((= uctr 1)
  1611.       (setq sent1 tmp)
  1612.       (dl_a01 brk_e1 "2" strtpt nil)  ; DLine_draw_Arc_0_and_1
  1613.       (dl_a01 brk_e2 "4" nextpt T)    ; DLine_draw_Arc_0_and_1
  1614.       (dl_mae nil T)
  1615.       (dl_mae nil nil)
  1616.       ;; Now break the line or arc found at the start point
  1617.       ;; if there is one, and we are in a breaking mood.
  1618.       (if (and dl:brk brk_e1)
  1619.         (progn
  1620.           (dl_mae T T)
  1621.           (dl_mae T nil)
  1622.           (command "break" brk_e1 savpt1 savpt2)
  1623.         )
  1624.       )
  1625.       ;; Do not set brk_e1 nil... it will be set later.
  1626.       ;; Now break the line or arc found at the end point 
  1627.       ;; if there is one, and we are in a breaking mood.
  1628.       (if (and dl:brk brk_e2)
  1629.         (progn
  1630.           (if (eq brk_e1 brk_e2)
  1631.             (progn
  1632.               ;; Delete both arcs so we can find the arc or line that
  1633.               ;; we found previously.
  1634.               (entdel (nth 0 wnames))  
  1635.               (entdel (nth 1 wnames))  
  1636.               (dl_ved "brk_e2" nextpt)
  1637.               ;; Restore first line
  1638.               (entdel (nth 0 wnames))
  1639.               (entdel (nth 1 wnames))
  1640.             )
  1641.           )
  1642.           (if (null brk_e1)
  1643.             (progn
  1644.               (dl_mae T T)
  1645.               (dl_mae T nil)
  1646.             )
  1647.           )
  1648.           (command "break" brk_e2 savpt3 savpt4)
  1649.         )
  1650.       )
  1651.       ;; Do not set brk_e2 nil... it will be set later.
  1652.     )
  1653.     ((= (rem uctr 2.0) 0) 
  1654.       (setq fang nil)
  1655.       (dl_da2)                        ; Draw arc part 2
  1656.       (if fang 
  1657.         (setq ftmp fang
  1658.               fang nil
  1659.         )
  1660.       )
  1661.       (setq save_1 ent)
  1662.       (setq sent1 (cdr(assoc -1 ent)))
  1663.       (setq pt2 (dl_a01 brk_e2 "3" nextpt T)) ; DLine_draw_Arc_0_and_1
  1664.       (if ftmp 
  1665.         (setq fang ftmp
  1666.               ftmp nil
  1667.         )
  1668.       )
  1669.     )
  1670.     (T
  1671.       (dl_da2)                        ; Draw arc part 2
  1672.       (if fang 
  1673.         (setq ftmp fang
  1674.               fang nil
  1675.         )
  1676.       )
  1677.       (setq save_2 ent)
  1678.       (setq sent1 (cdr(assoc -1 ent)))
  1679.       (setq pt2 (dl_a01 brk_e2 "4" nextpt T)) ; DLine_draw_Arc_0_and_1
  1680.       (if ftmp 
  1681.         (setq fang fang
  1682.               ftmp nil
  1683.         )
  1684.       )
  1685.  
  1686.       ;; Now break the line or arc found at the end point 
  1687.       ;; if there is one, and we are in a breaking mood.
  1688.       (if (and dl:brk brk_e2)
  1689.         (progn
  1690.           (dl_mae T T)
  1691.           (dl_mae T nil)
  1692.           (command "break" brk_e2 savpt3 savpt4)
  1693.         )
  1694.       )
  1695.       ;; Do not set brk_e2 nil... it will be set later.
  1696.     )
  1697.   )
  1698.   (setq uctr   (1+ uctr))
  1699. )
  1700. ;;;
  1701. ;;; Set pt1 or pt2 based on whether there is an arc or line to be broken.
  1702. ;;;
  1703. ;;; dl_a01 == DLine_draw_Arcs_0_and_1
  1704. ;;;
  1705. (defun dl_a01 (bent1 n pt flg / pt1 pt2 ang1 ang2 anga angb)
  1706.   ;; "n" is the point to save for end capping
  1707.   (setq n (strcat "savpt" n))
  1708.   ;; "tmp" is the arc just created.
  1709.   ;; "bent1" is the line or arc to be broken, if there is one...
  1710.   (if bent1
  1711.     (if (= (dl_val 0 bent1) "LINE")
  1712.       (progn
  1713.         (set (read n) (dl_ial tmp (trans (dl_val 10 bent1) 0 1)
  1714.                                   (trans (dl_val 11 bent1) 0 1) pt)) 
  1715.       )
  1716.       (progn
  1717.         (setq curcpt (trans (dl_val 10 sent1) (dl_val -1 sent1) 1) 
  1718.               prvcpt (trans (dl_val 10 bent1) (dl_val -1 bent1) 1)
  1719.               pt1    (polar prvcpt (dl_val 50 bent1) (dl_val 40 bent1))
  1720.               pt2    (polar curcpt (dl_val nn sent1) (dl_val 40 sent1))
  1721.               ang1   (angle prvcpt pt1)
  1722.         )
  1723.         (if (not (equal ang1 (angle prvcpt strtpt) 0.01))
  1724.           (setq pt1  (polar prvcpt (dl_val 51 bent1) (dl_val 40 bent1))
  1725.                 ang1 (angle prvcpt pt1)
  1726.                 ang2 (angle curcpt pt2)
  1727.                 anga (- ang1 ang2)
  1728.                 angb (- ang2 ang1)
  1729.           )
  1730.         )
  1731.         (if (or (and (< anga 0.0872665)
  1732.                      (> anga -0.0872665))
  1733.                 (and (< angb 0.0872665)
  1734.                      (> angb -0.0872665))
  1735.             )
  1736.           (progn
  1737.             (set (read n) pt)
  1738.             (if (= bent1 brk_e1) 
  1739.               (setq brk_e1 nil)
  1740.               (setq brk_e2 nil)
  1741.             )
  1742.           )
  1743.           (set (read n) (dl_iaa sent1 bent1 pt flg))
  1744.         )
  1745.       )
  1746.     )
  1747.     (progn
  1748.       (setq cpt (trans (dl_val 10 tmp) (dl_val -1 tmp) 1))
  1749.       (set (read n) (polar cpt (angle cpt pt) orad))
  1750.     )
  1751.   )
  1752.   (eval (read n))
  1753. )
  1754. ;;;
  1755. ;;; Do more of the arc drawing stuff.  This is where we call the modify 
  1756. ;;; functions for the previous arc or line segment.  The line end being
  1757. ;;; modified is always the group 11 end, but we have to test the start
  1758. ;;; and end angle of an arc to tell which end to modify.
  1759. ;;;
  1760. ;;; dl_da2 == DLine_Draw_Arc_segment_part_2
  1761. ;;;
  1762. (defun dl_da2 (/ pt)
  1763.   ;; get the corresponding previous entity
  1764.   (setq tmp1 (nth (- uctr 2) wnames) 
  1765.         ent1 (entget tmp1))
  1766.   (if (= (dl_val 0 tmp1) "LINE")     
  1767.     ;; if it's a line
  1768.     (setq pt (dl_mls T 11))             
  1769.     ;; if it's an arc
  1770.     (setq pt (dl_mas nil T nil nil strtpt)) 
  1771.   )
  1772.   ;; pt is a point in the current UCS, not ECS
  1773.   (if pt
  1774.     (progn
  1775.       (setq ang (- (angle cpt pt) ange))
  1776.       (entmod (setq ent (subst (cons nn ang) 
  1777.                        (assoc nn ent) 
  1778.                        ent)))         ; modify arc endpt
  1779.     )
  1780.   )
  1781.   (if flgn                            ; if closing 
  1782.     (progn
  1783.       (setq tmp1 (nth flgn wnames)     
  1784.             ent1  (entget tmp1))  ; get the flagged entity
  1785.       (if (= (dl_val 0 tmp1) "LINE")     
  1786.         ;; if it's a line
  1787.         (setq pt (dl_mls T 10))   
  1788.         ;; if it's an arc
  1789.         (setq pt (dl_mas T T nil nil nextpt)) 
  1790.       )
  1791.       (if pt
  1792.         (progn
  1793.           (setq ang (- (angle cpt pt) ange))
  1794.           (setq nn (if (= nn 50) 51 50))
  1795.           (entmod (setq ent (subst (cons nn ang) 
  1796.                          (assoc nn ent) 
  1797.                          ent)))       ; modify arc endpt
  1798.         )                             
  1799.       )
  1800.     )                             
  1801.   )
  1802. )
  1803. ;;;
  1804. ;;; Modify the endpoints of an arc by changing the start and end angles.
  1805. ;;;
  1806. ;;; dl_mae == DLine_Modify_Arc_Endpoints
  1807. ;;;
  1808. (defun dl_mae (eflg sflg / nn1 nn2)
  1809.   (if (= nn 50)
  1810.     (setq nn1 50 nn2 51)
  1811.     (setq nn1 51 nn2 50)
  1812.   )
  1813.   (if sflg
  1814.     (if eflg
  1815.       (setq save_1 (subst (cons nn2 
  1816.                                 (angle 
  1817.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1818.                                   (trans savpt3 1 (cdr(assoc -1 save_1)))
  1819.                                 )
  1820.                           )
  1821.                           (assoc nn2 save_1) save_1)
  1822.       )
  1823.       (setq save_1 (subst (cons nn1 
  1824.                                 (angle 
  1825.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1826.                                   (trans savpt1 1 (cdr(assoc -1 save_1)))
  1827.                                 )
  1828.                           )
  1829.                           (assoc nn1 save_1) save_1)
  1830.       )
  1831.     )
  1832.     (if eflg
  1833.       (setq save_2 (subst (cons nn2 
  1834.                                 (angle 
  1835.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1836.                                   (trans savpt4 1 (cdr(assoc -1 save_2)))
  1837.                                 )
  1838.                           )
  1839.                           (assoc nn2 save_2) save_2)
  1840.       )
  1841.       (setq save_2 (subst (cons nn1 
  1842.                                 (angle 
  1843.                                   (trans cpt    1 (cdr(assoc -1 save_1)))
  1844.                                   (trans savpt2 1 (cdr(assoc -1 save_2)))
  1845.                                 )
  1846.                           )
  1847.                           (assoc nn1 save_2) save_2)
  1848.       )
  1849.     )
  1850.   )
  1851.   (if sflg
  1852.     (entmod save_1)
  1853.     (entmod save_2)
  1854.   )
  1855. )
  1856. ;;;
  1857. ;;; Modify arc                        ; flg2 = nil if arc to line
  1858. ;;;                                   ;      = T   if arc to arc
  1859. ;;;
  1860. ;;; dl_mas == DLine_Modify_Arc_Segment
  1861. ;;;
  1862. (defun dl_mas (flg3 flg2 spt ept pt / nnn pt1 pt2 rad1 ange)
  1863.   ;; get some stuff
  1864.   (setq cpt1   (trans (dl_val 10 tmp1) (dl_val -1 tmp1) 1)           
  1865.         rad1   (dl_val 40 tmp1)
  1866.         ang1   (dl_val 50 tmp1)
  1867.   )
  1868.   (if (null pt)                       ; if a point is not passed in:
  1869.     (setq pt (nth 0 spts))            ; set to initial saved start point.
  1870.   )               
  1871.   (setq ange (trans '(1 0 0) (dl_val -1 tmp1) 1)
  1872.         ange (angle '(0 0 0) ange)
  1873.         ang1 (+ ang1 ange)
  1874.   )
  1875.   (if (> ang1 (* 2 pi))
  1876.     (setq ang1 (- ang1 (* 2 pi)))
  1877.   )
  1878.   (if (equal (angle cpt1 pt) ang1 0.01) ; figure out if we're looking
  1879.     (setq nnn 50)                     ; for the start or end point of
  1880.     (setq nnn 51)                     ; the beginning arc, then
  1881.   )                                   ; get the intersection point
  1882.   ;; if arc to arc
  1883.   (if flg2
  1884.     ;; then
  1885.     (progn
  1886.       ;; find intersection with arc
  1887.       (setq pt1 (dl_iaa tmp tmp1 (if flg3 nextpt strtpt) flg2))   
  1888.       (if pt1 
  1889.         (progn
  1890.           (setq ang1 (- (angle cpt1 pt1) ange))
  1891.           (setq ent1 (subst (cons nnn ang1) 
  1892.                             (assoc nnn ent1) 
  1893.                             ent1))                 
  1894.           (entmod ent1)               ; modify arc endpt
  1895.         )
  1896.       )
  1897.     )
  1898.     ;; else
  1899.     (progn 
  1900.       ;; find arc intersection with line from spt to ept
  1901.       (setq pt1 (dl_ial tmp1 spt ept pt)) 
  1902.       (setq ang1 (- (angle cpt1 pt1) ange))
  1903.       (setq ent1 (subst (cons nnn ang1) 
  1904.                         (assoc nnn ent1) 
  1905.                         ent1))                 
  1906.       (entmod ent1)                   ; modify arc endpt
  1907.     )
  1908.   )
  1909.   pt1
  1910. )
  1911. ;;; ---------------- Begin Arc to Arc Functions ---------------------
  1912. ;;;
  1913. ;;; This routine does a variety of tasks: it calculate up to two 
  1914. ;;; intersection points of two arcs,
  1915. ;;; then it attempts to determine which of the points serves as a 
  1916. ;;; best-fit to the following criteria:
  1917. ;;; 
  1918. ;;;   1) One end of the arc must lie "on" the arc. 
  1919. ;;;   2) Given that the point given in 1 above is pt1,
  1920. ;;;      and that the other point is pt2, then if the arc crosses over
  1921. ;;;      the other arc then use pt2, otherwise the arc does not cross over
  1922. ;;;      the other arc so use pt1.
  1923. ;;;      
  1924. ;;; If the two arcs do not intersect, then a line will be drawn
  1925. ;;; from the point of intersection of the arc and the perpendicular from
  1926. ;;; the line of the two arc centerpoints;  The arcs will be 
  1927. ;;; trimmed or extended as needed to meet these points.
  1928. ;;; 
  1929. ;;; If the two arcs are tangent, then they are
  1930. ;;; trimmed/extended to this point. 
  1931. ;;;
  1932. ;;; Intersection point of two arcs or circles
  1933. ;;; a    = radius of ename 1
  1934. ;;; b    = distance from curcpt to prvcpt
  1935. ;;; c    = radius of ename 2
  1936. ;;; curcpt = center point of first circle or arc  -- bent1, bent2, tmp
  1937. ;;; prvcpt = center point of second circle or arc -- sent1, sent2, tmp1
  1938. ;;; npt  = near point for nearest test
  1939. ;;;
  1940. ;;; dl_iaa == DLine_Intersect_Arc_and_Arc
  1941. ;;;
  1942. (defun dl_iaa  (en1 en2 npt flga / a b c s ang alpha alph ipt 
  1943.                                    curcpt prvcpt temp temp1 temp2)
  1944.   (setq curcpt  (trans (dl_val 10 en1) (dl_val -1 en1) 1) ; the "last" entity
  1945.         prvcpt  (trans (dl_val 10 en2) (dl_val -1 en2) 1) ; the previous entity
  1946.         a       (dl_val 40 en2)
  1947.         b       (distance curcpt prvcpt)
  1948.         c       (dl_val 40 en1)
  1949.         s       (/ (+ a b c) 2.0)
  1950.         ang     (angle curcpt prvcpt)
  1951.   )
  1952.   (cond
  1953.     ;; circles are tangent
  1954.     ;; If (- s a) == 0, this would cause a divide by zero below...
  1955.     ((or (= (- s a) 0) (equal b (+ a c) 0.001) (equal b (abs (- a c)) 0.001))
  1956.       ;; Circles are tangent.
  1957.       (setq ipt nil)
  1958.     )
  1959.     ;; circles do not intersect
  1960.     ((and (or (> b (+ a c)) (if (> c a) (< (+ a b) c) (< (+ c b) a)))                 
  1961.           (not (equal (+ a b ) c (/ (+ a b c) 1000000))))
  1962.       ;; No intersection.
  1963.       (if (= flg 4) 
  1964.         (progn
  1965.           (setq ipt (polar curcpt (angle curcpt prvcpt) c))
  1966.           (command "line" (polar prvcpt (angle prvcpt ipt) a) ipt "")
  1967.         )
  1968.         (progn
  1969.           (setq ipt (polar curcpt (angle curcpt prvcpt) c))
  1970.           (command "line" (polar prvcpt (angle prvcpt ipt) a) ipt "")
  1971.         )
  1972.       )
  1973.     )
  1974.     (T
  1975.       ;; general law of cosines formula -- (- s a) != 0
  1976.       (setq alpha (* 2.0 (atan (sqrt (abs (/ (* (- s b) (- s c)) 
  1977.                                              (* s (- s a)))))))
  1978.       )
  1979.       
  1980.       (setq tpt1 (polar curcpt (+ ang alpha) c)
  1981.             tpt2 (polar curcpt (- ang alpha) c)
  1982.             anga  (angle curcpt npt)
  1983.             angb  (angle prvcpt npt)
  1984.       )
  1985.       ;; Two intersections. Now...
  1986.       ;; If drawing arcs, fang is set, we're past the first segment...
  1987.       ;; Reset the `near' point based on the previous ipt.  This can be
  1988.       ;; quite different and necessary from the `npt' passed in.
  1989.       (if (and dl_arc fang (> uctr 1)) 
  1990.         (setq npt (polar prvcpt fang c))
  1991.       )
  1992.       (if (< (distance tpt1 npt) (distance tpt2 npt))
  1993.         (setq temp tpt1
  1994.               tpt1 tpt2
  1995.               tpt2 temp
  1996.         )
  1997.       )
  1998.       (setq temp (angle prvcpt curcpt)) ; angle from prev ent to this ent
  1999.       (setq ipt (dl_bap en1 en2 tpt2 tpt1 nil))
  2000.       (if fang 
  2001.         (setq fang nil)
  2002.         (if dl_arc (setq fang (angle cpt ipt)))
  2003.       )
  2004.     )
  2005.   )
  2006.   (setq cpt curcpt)
  2007.   (setq cpt1 prvcpt)
  2008.   ipt                                 ; return point
  2009. )
  2010. ;;;
  2011. ;;; Get the best point for the arc/arc intersection.
  2012. ;;;
  2013. ;;; dl_bap == DLine_Best_Point_to_Arc
  2014. ;;;
  2015. (defun dl_bap (en1 en2 pp1 pp2 flg / temp1 temp2)
  2016.   (setq temp1 (dl_ona en1 pp2)
  2017.         temp2 (dl_ona en2 pp2)
  2018.   )
  2019.   (if temp2
  2020.     (if (and (< uctr 2) 
  2021.              (and brk_e1 brk_e2))
  2022.       pp1
  2023.       (if (and temp1 (not fang)) pp2 pp1) ;;;;pp2
  2024.     )
  2025.     pp1
  2026.   )        
  2027. )
  2028. ;;; ----------------- End Arc  Drawing Functions --------------------
  2029. ;;; -------------------- Begin Misc Functions -----------------------
  2030. ;;;
  2031. ;;; Add the entity name to the list in wnames.
  2032. ;;;
  2033. ;;; dl_atl == DLine_Add_To_List
  2034. ;;;
  2035. (defun dl_atl ()
  2036.   (setq wnames (if (null wnames) 
  2037.                  (list (entlast)) 
  2038.                  (append wnames (list tmp)))
  2039.   )
  2040.   wnames
  2041. )
  2042. ;;;
  2043. ;;; The value of the assoc number of <ename>
  2044. ;;;
  2045. (defun dl_val (v temp)
  2046.   (cdr(assoc v (entget temp)))
  2047. )
  2048. ;;;
  2049. ;;; List stripper : strips the last "v" members from the list
  2050. ;;;
  2051. (defun dl_lsu (lst v / m)
  2052.   (setq m 0 temp '())
  2053.   (repeat (- (length lst) v)
  2054.     (progn
  2055.       (setq temp (append temp (list (nth m lst))))
  2056.       (setq m (1+ m))
  2057.   ) )
  2058.   temp
  2059. )
  2060. ;;;
  2061. ;;; Bitwise DLINE endcap setting function.
  2062. ;;;
  2063. (defun endcap ()
  2064.   (initget "Auto Both End None Start")
  2065.   (setq dl:ecp (getkword 
  2066.     "\nDraw which endcaps?  Both/End/None/Start/<Auto>: "))
  2067.   (cond
  2068.     ((= dl:ecp "None")
  2069.       (setq dl:ecp 0)
  2070.     )
  2071.     ((= dl:ecp "Start")
  2072.       (setq dl:ecp 1)
  2073.     )
  2074.     ((= dl:ecp "End")
  2075.       (setq dl:ecp 2)
  2076.     )
  2077.     ((= dl:ecp "Both")
  2078.       (setq dl:ecp 3)
  2079.     )
  2080.     (T  ; Auto
  2081.       (setq dl:ecp 4)
  2082.     )
  2083.   )
  2084. )
  2085. ;;;
  2086. ;;; Set these defaults when loading the routine.
  2087. ;;;
  2088. (if (null dl:ecp) (setq dl:ecp 4))    ; default to auto endcaps
  2089. (if (null dl:snp) (setq dl:snp T))    ; default to snapping ON
  2090. (if (null dl:brk) (setq dl:brk T))    ; default to breaking ON
  2091. (if (null dl:osd) (setq dl:osd 0))    ; default to center alignment
  2092. ;;;
  2093. ;;; These are the c: functions.
  2094. ;;;
  2095. (defun c:dl () (vmon) (dline))
  2096. (defun c:dline () (vmon) (dline))
  2097. (princ "\n\tC:DLine loaded.  Start command with DL or DLINE.")
  2098. (princ)
  2099.